﻿/**************************************************************
 *
 * 唯一标识：1903f1c2-d8c3-43e2-9a74-802cd0bfddbe
 * 命名空间：Sgr.EntityFrameworkCore
 * 创建时间：2023/8/4 9:19:41
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using Microsoft.EntityFrameworkCore;
using Sgr.Data;
using Sgr.Domain.Entities;
using Sgr.Domain.Uow;

namespace Sgr.EntityFrameworkCore
{
    /// <summary>
    /// DbContext基类
    /// </summary>
    public abstract class UnitOfWorkDbContext : DbContext
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="options">DbContext选项</param>
        public UnitOfWorkDbContext(DbContextOptions options)
            : base(options)
        {
        }

        /// <summary>
        /// 初始化数据库上下文
        /// </summary>
        /// <param name="option">工作单元选项</param>
        /// <remarks>
        /// 根据工作单元选项配置数据库上下文：
        /// 1. 如果指定了超时时间（Timeout）
        /// 2. 且数据库是关系型数据库（IsRelational）
        /// 3. 且未设置命令超时时间
        /// 则设置数据库命令超时时间
        ///
        /// 注意：
        /// - 超时时间单位为毫秒
        /// - 仅对关系型数据库有效
        /// - 已设置的命令超时时间不会被覆盖
        /// </remarks>
        /// <exception cref="ArgumentNullException">当 <paramref name="option"/> 为 null 时抛出</exception>
        public virtual void Initialize(UnitOfWorkOption option)
        {
            Check.NotNull(option, nameof(option));

            if (option.Timeout.HasValue
                && Database.IsRelational()
                && !Database.GetCommandTimeout().HasValue)
            {
                Database.SetCommandTimeout(TimeSpan.FromMilliseconds(option.Timeout.Value));
            }
        }

        ///// <summary>
        ///// 获取DbContext的数据库连接字符串
        ///// </summary>
        ///// <returns></returns>
        //public virtual string GetDbContextConnectionString()
        //{
        //    return Database.GetDbConnection().ConnectionString;
        //}

        #region 判定数据库类型

        ///// <summary>
        ///// 数据库是否支持Decimal类型
        ///// </summary>
        ///// <returns></returns>
        //public virtual bool CheckSupportDecimal()
        //{
        //    return Database.ProviderName?.IndexOf("Sqlite", StringComparison.OrdinalIgnoreCase) >= 0;
        //}

        #endregion 判定数据库类型

        #region 扩展功能

        /// <summary>
        /// 物理删除实体
        /// </summary>
        /// <typeparam name="TEntity">实体类型</typeparam>
        /// <param name="entity">要删除的实体</param>
        /// <returns>异步任务</returns>
        public virtual void PhysicalDelete<TEntity>(
            TEntity entity)
            where TEntity : class, ISoftDelete
        {
            Check.NotNull(entity, nameof(entity));

            Set<TEntity>().Remove(entity);
        }

        #endregion 扩展功能
    }
}